package dp.mobile.game;

import android.graphics.Point;
import android.view.MotionEvent;
import dp.mobile.glwrapper.GameRenderer;
import dp.mobile.system.Utilities;

public class GameTouchListener extends AdvancedTouchListener {
	private static final String TAG = "Game Touch Listener";
	public GameTouchListener(Game game) {
		super();
		mGame = game;
	}
	
	@Override
	protected boolean onLongPress(MotionEvent event) {
		onClick(event);
		
		
		return true;
	}
	
	@Override
	protected boolean onRelease(MotionEvent event) {
		mEdgeScrolling 	= false;
		mScrollFlag 	= 0;
		return false;
	}
	
	@Override
	protected boolean onClick(MotionEvent event) {
		if (mGame.getPlayer().hasWon()) {
			mGame.getListener().onWinPressed(mGame.getLevelName(), mGame.getPlayer().getScore());
			return true;
		} else if (mGame.isPaused())
			return false;
		GameRenderer renderer = GameRenderer.instance();
		
		final float scaleX = renderer.getScale().x;
		final float scaleY = renderer.getScale().y;
		
		final float depth = renderer.getDepth();
		final int mappedX = (int)((event.getX() + renderer.getOffset().x * scaleX / depth - Utilities.SCREEN_WIDTH * scaleX / 2 ) / scaleX / Utilities.TILE_WIDTH * -depth);
		final int mappedY = (int)((event.getY() - renderer.getOffset().y * scaleY / depth - Utilities.SCREEN_HEIGHT * scaleY / 2) / scaleY / Utilities.TILE_HEIGHT * -depth);
		
		if (mappedX < 0 || mappedX >= mGame.getMap().getWidth() || mappedY < 0 || mappedY >= mGame.getMap().getHeight())
			return true;
		
		mGame.getPlayer().setSelectedTile(mappedX, mappedY);
		
		if (mGame.getMap().isTileBuildable(mappedX, mappedY)) 
			mGame.getPlayer().setCursorType(Utilities.CURSOR_DEFAULT);
		else
			mGame.getPlayer().setCursorType(Utilities.CURSOR_DISABLED);
		
		
		if (!mGame.isPaused())
			mGame.showPanel();
			//mGame.getListener().onPanelShow();
		
		return true;
	}
	
	@Override
	protected boolean onSwipe(MotionEvent event) {
		GameRenderer renderer = GameRenderer.instance();

		final float scaleX = renderer.getScale().x;
		final float scaleY = renderer.getScale().y;
		final float dOffsetX = (event.getX() - mLastPoint[1].x);
		final float dOffsetY = (event.getY() - mLastPoint[1].y);
		
		Point offset = renderer.getOffset();
		offset.set(offset.x + (int)(dOffsetX / (scaleX * Utilities.SCROLL_FACTOR)), offset.y - (int)(dOffsetY / (scaleY * Utilities.SCROLL_FACTOR)));
		
		GameRenderer.instance().checkOffset(mGame.getMap().getWidth() * Utilities.TILE_WIDTH, mGame.getMap().getHeight() * Utilities.TILE_HEIGHT);
		
		final int normalizedX = (int)(event.getX()  / scaleX);
		final int normalizedY = (int)(event.getY()  / scaleY);
		
		if (normalizedX < Utilities.SCREEN_WIDTH / 6 && dOffsetX < 0)
			mScrollFlag |= EDGE_LEFT_FLAG;
		if (normalizedX > Utilities.SCREEN_WIDTH / 6 * 5 && dOffsetX > 0)
			mScrollFlag |= EDGE_RIGHT_FLAG;
		if (normalizedY < Utilities.SCREEN_HEIGHT / 4 && dOffsetY < 0)
			mScrollFlag |= EDGE_UP_FLAG;
		if (normalizedY > Utilities.SCREEN_HEIGHT / 4 * 3 && dOffsetY > 0)
			mScrollFlag |= EDGE_DOWN_FLAG;
		
		if (mScrollFlag != 0) {
			if (mEdgeScroller == null || !mEdgeScroller.isAlive()) {
				mEdgeScroller = new Thread() {
					@Override
					public void run() {
						mEdgeScrolling = true;
						while (mEdgeScrolling) {
							synchronized (GameRenderer.instance()) {
							
								GameRenderer renderer = GameRenderer.instance();
	
								final float scaleX = renderer.getScale().x;
								final float scaleY = renderer.getScale().y;
								int dX = 0;
								int dY = 0;
								
								Point offset = renderer.getOffset();
								// left
								if ((mScrollFlag & EDGE_LEFT_FLAG) > 0) 
									dX = -(int)(10 / (scaleX * Utilities.SCROLL_FACTOR));
								// right
								if ((mScrollFlag & EDGE_RIGHT_FLAG) > 0)
									dX = (int)(10 / (scaleX * Utilities.SCROLL_FACTOR));
								// up
								if ((mScrollFlag & EDGE_UP_FLAG) > 0) 
									dY = (int)(10 / (scaleY * Utilities.SCROLL_FACTOR));
								// down
								if ((mScrollFlag & EDGE_DOWN_FLAG) > 0)
									dY = -(int)(10 / (scaleY * Utilities.SCROLL_FACTOR));
								
								offset.set(offset.x + dX, offset.y + dY);
								
								GameRenderer.instance().checkOffset(mGame.getMap().getWidth() * Utilities.TILE_WIDTH, mGame.getMap().getHeight() * Utilities.TILE_HEIGHT);
								
							}
							
							try {
								sleep(32);
							} catch (InterruptedException iEx) {}
						}
					}
				};
				mEdgeScroller.start();
			}
		}
		
		mLastPoint[1].x = event.getX();
		mLastPoint[1].y = event.getY();
		
		return true;
	}
	
	@Override
	protected boolean onPinch(MotionEvent event) {
		GameRenderer renderer = GameRenderer.instance();
		
		final float dx1 = (mLastPoint[0].x - mLastPoint[1].x) / renderer.getScale().x;
		final float dy1 = (mLastPoint[0].y - mLastPoint[1].y) / renderer.getScale().y;
		final float firstDistance =  (float)Math.sqrt((dx1 * dx1) + (dy1 * dy1));
		
		for (int i = 0; i < 2; ++i) {
			mLastPoint[i + 2].x = event.getX(i);
			mLastPoint[i + 2].y = event.getY(i);
		}
		
		mLastPoint[0].set(mLastPoint[2]);
		mLastPoint[1].set(mLastPoint[3]);
		
		final float dx2 = (mLastPoint[2].x - mLastPoint[3].x) / renderer.getScale().x;
		final float dy2 = (mLastPoint[2].y - mLastPoint[3].y) / renderer.getScale().y;
		final float lastDistance = (float)Math.sqrt((dx2 * dx2) + (dy2 * dy2));
		
		final float nextDepth = renderer.getDepth() + (lastDistance - firstDistance) / 100.0f;
		
		renderer.setDepth(nextDepth);
		
		return true;
	}
	
	private Thread mEdgeScroller;
	private static final int EDGE_LEFT_FLAG 	= 1;
	private static final int EDGE_UP_FLAG 		= 2;
	private static final int EDGE_RIGHT_FLAG 	= 4;
	private static final int EDGE_DOWN_FLAG 	= 8;
	private int mScrollFlag;
	private Game mGame;
	private boolean mEdgeScrolling;
}
